package com.lizhi.yun.core.login.handler;/**
 * @program: spring-boot
 * @name LoginHandler
 * @description: 登录service
 * @author: lizhi
 * @create: 2020-04-11 16:49
 */

import com.lizhi.common.yun.entity.ListResponseResult;
import com.lizhi.common.yun.enums.OrganStateEnum;
import com.lizhi.yun.db.dao.UppMenuDao;
import com.lizhi.yun.db.dao.UppRoleDao;
import com.lizhi.yun.db.dao.UppRoleMenuDao;
import com.lizhi.yun.db.dao.UppUserDao;
import com.lizhi.utils.DateUtils;
import com.lizhi.utils.StringUtils;
import com.lizhi.utils.cache.MemoryCacheUtil;
import com.lizhi.utils.token.TokenUtil;
import com.lizhi.utils.tools.MD5Util;
import com.lizhi.yun.base.BaseHandler;
import com.lizhi.yun.base.UppSysUtil;
import com.lizhi.yun.db.pojo.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;

/**
 *@program: spring-boot
 *@name LoginHandler
 *@description: 登录service
 *@author: lizhi
 *@create: 2020-04-11 16:49
 */
@Slf4j
@Service
public class LoginHandler extends BaseHandler {

    @Resource
    private UppUserDao uppUserDao;

    @Resource
    private UppRoleMenuDao uppRoleMenuDao;

    @Resource
    private UppMenuDao uppMenuDao;

    @Resource
    private UppRoleDao uppRoleDao;

    /**
     *功能描述
     * @author lizhi
     * @date 2020/4/11
     * @param userAcct:
     * @param password:
     * @return java.lang.String
     */
    public ListResponseResult doLogin(String userAcct, String password){
        if (StringUtils.isEmpty(userAcct) || StringUtils.isEmpty(password)){
            return getListResult(null, false);
        }
        UppUserPOJO uppUserPOJO = uppUserDao.selectById(userAcct);
        if (uppUserPOJO == null){
            return getListResult(null, false);
        }
        if (uppUserPOJO.getUserPwd().equals(MD5Util.getMD5(password))) {
            uppUserPOJO.setPwdErrCnt(0);
            /*修改上次登录信息*/
            uppUserPOJO.setLastLoginTm(uppUserPOJO.getUpdTm());
            uppUserPOJO.setUpdTm(DateUtils.getNowDate());
            uppUserDao.updateByIdSelective(uppUserPOJO);
            log.info("用户{}登录成功。", uppUserPOJO.getUserAcct());
            /*以逗号分隔开权限id*/
            String[] roleIds = uppUserPOJO.getRoleIds().split(",");
            StringBuffer stringBuffer = new StringBuffer();
            for (int i = 0; i < roleIds.length; i++){
                UppRolePOJO uppRolePOJO = uppRoleDao.selectById(roleIds[i]);
                if (i == roleIds.length -1){
                    stringBuffer.append(uppRolePOJO.getRoleNm());
                } else {
                    stringBuffer.append(uppRolePOJO.getRoleNm() + ",");
                }
            }
            uppUserPOJO.setRoleNms(stringBuffer.toString());
            String token = TokenUtil.sign(userAcct);
            uppUserPOJO.setToken(token);
            MemoryCacheUtil.put(userAcct, token);
            return getListResult(uppUserPOJO);
        } else {
            return getListResult(null, false);
        }
    }

    /**
     * 退出登录，清除缓存
     * @param userAcct
     * @return
     */
    public ListResponseResult doSignout(String userAcct){
        /*清除缓存*/
        MemoryCacheUtil.remove(userAcct);
        return getListResult(true);
    }
    /**
     *功能描述  获取菜单
     * @author lizhi
     * @date 2020/4/11
     * @param userAcct:
     * @return java.lang.String
     */
    public ListResponseResult doMenu(String userAcct) {
        UppUserPOJO uppUserPOJO = uppUserDao.selectById(userAcct);
        //获取当前用户  所有角色id
        List<String> roleIds = StringUtils.toListByComma(uppUserPOJO.getRoleIds());
        if (CollectionUtils.isEmpty(roleIds)) {
            return null;
        }
        List<String> normalRoleIds = getNormalRoles(roleIds);
        if (CollectionUtils.isEmpty(normalRoleIds)) {
            return null;
        }

        //通过角色id 选取出菜单
        List<UppRoleMenuPOJO> roleMenus = uppRoleMenuDao.selectByRoleIds(normalRoleIds);
//        log.info("获取到的该用户名下所有的菜单roleMenus:{}",roleMenus);
        if (CollectionUtils.isEmpty(roleMenus)) {
            return null;
        }

        Map<String, String> roleMenuIds = new HashMap<>();
        for (UppRoleMenuPOJO roleMenuDO : roleMenus) {
            roleMenuIds.put(roleMenuDO.getMenuId(), roleMenuDO.getButtonIds());
        }
        //查询出所有的菜单
        List<UppMenuPOJO> allMenu = uppMenuDao.findAll();
        if (CollectionUtils.isEmpty(allMenu)) {
            return null;
        }
        /*将菜单转化成map（menuid,UppMenuPOJO）*/
        Map<String, UppMenuPOJO> menuDOMap = UppSysUtil.getMenuMap(allMenu);

        /*顶级菜单*/
        Set<String> rootkeys = new HashSet<>();
        Map<String, MenuLevelPOJO> menuLevelVOMap = new HashMap<>();
        for (String roleMenuId : roleMenuIds.keySet()) {
            UppMenuPOJO menuDO = menuDOMap.get(roleMenuId);
            if (menuDO != null) {
                getMenuLevelPOJO(menuDOMap, menuDO, null, menuLevelVOMap, rootkeys);
            }
        }
        List<MenuLevelPOJO> roots = new ArrayList<>();
        for (String key : rootkeys) {
            roots.add(menuLevelVOMap.get(key));
        }
        sort(roots);
        return getListResult(roots);
    }

    private void getMenuLevelPOJO(Map<String, UppMenuPOJO> menuDOMap, UppMenuPOJO menuDO, MenuLevelPOJO childVO, Map<String, MenuLevelPOJO> menuLevelVOMap,
                                Set<String> rootkeys) {
        MenuLevelPOJO menuLevelPOJO = menuLevelVOMap.get(menuDO.getMenuId());
        if (menuLevelPOJO == null) {
            menuLevelPOJO = UppSysUtil.getMenuLevelVO(menuDO);
            menuLevelVOMap.put(menuDO.getMenuId(), menuLevelPOJO);
        }
        if (childVO != null) {
            /*获取目前已经存在的菜单*/
            List<MenuLevelPOJO> child = menuLevelPOJO.getChildren();
            if (!StringUtils.isEmpty(child)){
                int count = child.size();
                boolean flag = true;
                for (int j = 0; j < count; j++){
                    MenuLevelPOJO vo = child.get(j);
                    if (vo.getMenuId().equals(childVO.getMenuId())) {
                        flag = false;
                    }
                }
                if (flag){
                    child.add(childVO);
                }
            } else {
                child = new ArrayList<>();
                child.add(childVO);
            }
            menuLevelPOJO.setChildren(child);
        }
        if (StringUtils.isEmpty(menuDO.getParentMenuId())) {
            rootkeys.add(menuDO.getMenuId());
            return;
        }
        UppMenuPOJO p = menuDOMap.get(menuDO.getParentMenuId());
        if (p == null) {
            return;
        }
        getMenuLevelPOJO(menuDOMap, p, menuLevelPOJO, menuLevelVOMap, rootkeys);
    }

    private void sort(List<MenuLevelPOJO> list) {
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        for (MenuLevelPOJO vo : list) {
            sort(vo.getChildren());
        }
        Collections.sort(list, menuComparator);
    }

    private Comparator<MenuLevelPOJO> menuComparator = new Comparator<MenuLevelPOJO>() {
        @Override
        public int compare(MenuLevelPOJO o1, MenuLevelPOJO o2) {
            int m = o1.getMenuOdr() == null ? Integer.MAX_VALUE : o1.getMenuOdr();
            int n = o2.getMenuOdr() == null ? Integer.MAX_VALUE : o2.getMenuOdr();
            if (m > n) {
                return 1;
            } else if (m < n) {
                return -1;
            }
            return 0;
        }
    };


    /**
     * 方法描述：将角色id数组中，角色id对应角色状态不为正常的剔除
     * @param roleIds
     * @return List<String>
     */
    private List<String> getNormalRoles(List<String> roleIds){
        List<String> normalRoleId = new ArrayList<String>();
        for(String roleId:roleIds){
            UppRolePOJO uppRoleDo =  uppRoleDao.selectById(roleId);
            if(isNormalState(uppRoleDo)){
                normalRoleId.add(roleId);
            }
        }
        return normalRoleId;
    }

    /**
     * 方法描述：判断角色状态是否为正常，如为正常返回true，反之返回false
     * @param uppRoleDo
     * @return Boolean
     */
    private Boolean isNormalState(UppRolePOJO uppRoleDo){
        if(null == uppRoleDo){
            return false;
        }
        if(!OrganStateEnum.NORMAL.getEnValue().equals(uppRoleDo.getState())){
            return false;
        }
        return true;
    }
}
